package com.hq;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * 群聊
 * 接收客户端的信息转发给其他客户端  排除自己    上线先通知
 */
public class GroupChatService {
    public GroupChatService() throws IOException {
        init();
    }
    Selector selector;
    public void init() throws IOException {
        //建立一个服务器 用来接收连接 和转发连接
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        selector = Selector.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8888));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        System.out.println("服务启动 开始监听");
        try {
            while (true){
                int count = selector.select(4000);
                if(count > 0){
                    //如果有事件发生 处理不同事件
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()){
                        SelectionKey key = iterator.next();
                        if(key.isAcceptable()){
                            //连接事件发生  把通道注册成读事件
                            SocketChannel channel = serverSocketChannel.accept();
                            channel.configureBlocking(false);
                            channel.register(selector,SelectionKey.OP_READ);
                            System.out.println("有客户端上线："+channel.getRemoteAddress().toString());
                        }
                        if(key.isReadable()){
                            //读事件发生 读到消息后发送到别的客户端去
                            readData(key);

                        }
                        //清理处理完的时间
                        iterator.remove();
                    }
                }else {
                    //没有事件 不处理
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void readData(SelectionKey key) throws IOException {
        SocketChannel channel = null;
        try {
            //读到消息  发送消息
            channel = (SocketChannel) key.channel();
            ByteBuffer allocate = ByteBuffer.allocate(1024);
            int read = channel.read(allocate);
            if(read > 0){
                String msg = new String(allocate.array());
                System.out.println("收到客户端消息"+msg);
                sendInfoToOrderClients(msg,channel);
            }
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("客户端下线了"+channel.getRemoteAddress().toString());
            key.cancel();
            channel.close();
        }

    }

    /**
     * 发送消息到各个客户端  排除发送的管道
     * @param msg
     * @param socketChannel
     */
    private void sendInfoToOrderClients(String msg, SocketChannel socketChannel) throws IOException {
        System.out.println("开始转发消息");
        Iterator<SelectionKey> iterator = selector.keys().iterator();
        while (iterator.hasNext()){
            SelectionKey key = iterator.next();
            Channel targetClient =  key.channel();
            if(targetClient instanceof SocketChannel && !targetClient.equals(socketChannel)){
                //写入带其他客户端的管道中
                SocketChannel dest = (SocketChannel)targetClient;
                ByteBuffer message = ByteBuffer.wrap(msg.getBytes());
                dest.write(message);
            }
        }
    }

    public static void main(String[] args) throws IOException {
        GroupChatService groupChatService = new GroupChatService();
    }
}
